//
// Created by lz on 2/27/21.
//

#ifndef MYWEBLIB_NET_CHANNEL_H
#define MYWEBLIB_NET_CHANNEL_H

#include "base/noncopyable.h"
#include "base/Timestamp.h"
#include <functional>
#include <memory>


namespace lzweb
{
namespace net
{
class EventLoop;

///
/// A selectable I/O channel.
///
/// This class doesn't own the file descriptor.
/// The file descriptor could be a socket,
/// an eventfd, a timerfd, or a signalfd
class Channel: noncopyable
{
public:
	using EventCallback = std::function<void()>;
	using ReadEventCallback = std::function<void(TimeStamp)>;

	Channel(EventLoop *loop, int fd);
	~Channel();

	void handleEvent(TimeStamp receiveTime);

	void setReadCallback(ReadEventCallback cb)
	{ readCallback_ = std::move(cb); }
	void setWriteCallback(EventCallback cb)
	{ writeCallback_ = std::move(cb); }
	void setCloseCallback(EventCallback cb)
	{ closeCallback_ = std::move(cb); }

	void setErrorCallback(EventCallback cb)
	{ errorCallback_ = std::move(cb); }

	/// Tie this channel to the owner object managed by shared_ptr,
	/// prevent the owner object being destroyed in handleEvent.

	void tie(const std::shared_ptr<void> &);

	int fd() const
	{ return fd_; }
	int events() const
	{ return events_; }
	void set_revents(int revt)
	{ revents_ = revt; } //used by pollers
	// int revents() const { return revents_; }
	bool isNoneEvent() const
	{ return events_ == kNoneEvent; }


	//设置文件描述符中的事件
	void enableReading()
	{
		events_ |= kReadEvent;
		update();
	}
	void disableReading()
	{
		events_ &= ~kReadEvent;
		update();
	}

	void enableWriting(){ events_|= kWriteEvent; update();}
	void disableWriting() { events_ &= ~kWriteEvent; update();}
	void disableAll() { events_ = kNoneEvent; update();}

	bool isWriting() const { return events_ & kWriteEvent;}
	bool isReading() const { return events_ & kReadEvent; }

	// for Poller
	int index() const { return index_;}
	void set_index(int idx) { index_ = idx; }

	//for debug
	string reventsToString() const;
	string eventsToString() const;

	void doNotLogHup() { logHup_ = false; }

	EventLoop* ownerLoop(){ return loop_; }

	void remove();



private:
	static string eventToString(int fd, int ev);

	void update();
	void handleEventWithGuard(TimeStamp receiveTime);

	static const int kNoneEvent;
	static const int kReadEvent;
	static const int kWriteEvent;

	EventLoop *loop_;
	const int fd_;
	int events_;   //记录上面的文件描述符的关注事件
	int revents_;  // it's the received event types of epoll or poll      即从poll或epoll返回的触发事件
	int index_;  // used by Poller    pollpoller 记录该channel在 channellist中 的索引   epollpoller 用于记录该fd在epoll中的状态（new ,deleted, added ）
	bool logHup_;  //标志是否记录POLLHUP情况

	std::weak_ptr<void> tie_;   //目前看到会tie到一个TcpConnection
	bool tied_;
	bool eventHandling_;  //记录当前的Channel是否正在被处理
	bool addedToLoop;   //记录该Channel是否被loop_记录
	ReadEventCallback readCallback_;
	EventCallback writeCallback_;
	EventCallback closeCallback_;
	EventCallback errorCallback_;

};
}

}// namespace lzweb


#endif //MYWEBLIB_NET_CHANNEL_H
